package com.cjj.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cjj.common.convention.errorcode.BaseErrorCode;
import com.cjj.common.convention.exception.ClientException;
import com.cjj.common.convention.exception.ServiceException;
import com.cjj.common.convention.result.Result;
import com.cjj.common.convention.result.Results;
import com.cjj.dao.entity.User;
import com.cjj.dao.mapper.UserMapper;
import com.cjj.dto.req.*;
import com.cjj.dto.resp.UserListRespDTO;
import com.cjj.dto.resp.UserLoginRespDTO;
import com.cjj.service.UserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

import static com.cjj.common.enums.UserErrorCodeEnum.*;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author admin
 * @since 2025-10-25
 */

@Slf4j
@Service
@RequiredArgsConstructor //构造器注入
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;

    @Override
    public Result<Void> register(UserRegisterReqDTO registerDTO) {
        // 一次查询检查所有唯一字段
        String conflictField = checkUserConflicts(registerDTO);
        if (conflictField != null) {
            //throw new CustomException("400", getConflictMessage(conflictField));
            return Results.failure(BaseErrorCode.USER_NAME_EXIST_ERROR.code(),BaseErrorCode.USER_NAME_EXIST_ERROR.message());
        }

        // 使用 BeanUtil.copyProperties
        User user = BeanUtil.copyProperties(registerDTO, User.class);
        user.setPassword(passwordEncoder.encode(registerDTO.getPassword()))
                .setRole("student")
                .setStatus(1)
                .setCreateTime(LocalDateTime.now());


        int count = userMapper.insert(user);
        if (count != 1) {
            return Results.failure();
        }
        return Results.success();
    }

    /**
     * 一次查询检查所有冲突字段
     * @return 冲突的字段名，无冲突返回null
     */
    private String checkUserConflicts(UserRegisterReqDTO registerDTO) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, registerDTO.getUsername())
                .or().eq(User::getPhone, registerDTO.getPhone())
                .or().eq(User::getEmail, registerDTO.getEmail());

        User existingUser = userMapper.selectOne(wrapper);
        if (existingUser == null) {
            return null; // 无冲突
        }

        // 确定具体是哪个字段冲突
        if (existingUser.getUsername().equals(registerDTO.getUsername())) {
            return "username";
        }
        return "unknown";
    }

    /**
     * 根据冲突字段返回错误信息
     */
    private String getConflictMessage(String conflictField) {
        switch (conflictField) {
            case "username": return "用户名已存在";
            case "phone": return "手机号已注册";
            case "email": return "邮箱已注册";
            default: return "用户信息已存在";
        }
    }

    @Override
    public boolean isUsernameExists(String username) {
        return userMapper.exists(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username));
    }

    @Override
    public boolean isPhoneExists(String phone) {
        return userMapper.exists(new LambdaQueryWrapper<User>()
                .eq(User::getPhone, phone));
    }

    @Override
    public boolean isEmailExists(String email) {
        return userMapper.exists(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, email));
    }


    /**
     * 通过用户id修改用户信息
     * @param userUpdateReqDTO
     */

    @Override
    public void updateByUserId(UserUpdateReqDTO userUpdateReqDTO) {
        LambdaUpdateWrapper<User> eq = Wrappers.lambdaUpdate(User.class)
                .eq(User::getUserId,userUpdateReqDTO.getUserId());
        userUpdateReqDTO.setStatus(1);
        int count = baseMapper.update(BeanUtil.copyProperties(userUpdateReqDTO, User.class), eq);
        if (count < 1) {
            throw new ServiceException(BaseErrorCode.USER_UPDATE_ERROR);
        }
    }

    /*
    用户登录
     */
    @Override
    public UserLoginRespDTO login(UserLoginReqDTO userLoginReqDTO) {
        LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery(User.class)
                .eq(User::getUsername, userLoginReqDTO.getUsername())
                .eq(User::getPassword, userLoginReqDTO.getPassword());
        User user = baseMapper.selectOne(queryWrapper);
        if (user == null) {
            throw new ClientException(USER_NULL);
        }
        if (user.getStatus() == 0){
            throw new ClientException(USER_DISABLED);
        }
        return BeanUtil.copyProperties(user, UserLoginRespDTO.class);
    }

    /*
    分页查询用户
     */
    @Override
    public IPage<UserListRespDTO> getUserList(Integer pageNum, Integer pageSize, UserListReqDTO userListReqDTO) {
        // 校验分页参数
        pageNum = (pageNum == null || pageNum < 1) ? 1 : pageNum;
        pageSize = (pageSize == null || pageSize < 1) ? 10 : pageSize;
        pageSize = Math.min(pageSize, 100); // 限制最大页大小


        // 创建分页对象
        Page<User> page = new Page<>(pageNum, pageSize);

        // 构建查询条件
        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class)
                .eq(User::getUserType, 1)
                .orderByDesc(User::getCreateTime);

        // 只有当 userListReqDTO 不为 null 时才添加条件
        if (userListReqDTO != null) {
            wrapper.eq(StrUtil.isNotBlank(userListReqDTO.getRole()), User::getRole, userListReqDTO.getRole())
                    .eq(User::getStatus, userListReqDTO.getStatus())
                    .eq(StrUtil.isNotBlank(userListReqDTO.getPhone()), User::getPhone, userListReqDTO.getPhone())
                    .eq(StrUtil.isNotBlank(userListReqDTO.getEmail()), User::getEmail, userListReqDTO.getEmail())
                    .like(StrUtil.isNotBlank(userListReqDTO.getName()), User::getName, userListReqDTO.getName());
        }

        // 执行分页查询
        Page<User> userPage = baseMapper.selectPage(page, wrapper);

        // 直接转换并返回 IPage
        return userPage.convert(user -> BeanUtil.copyProperties(user, UserListRespDTO.class));
    }

    /*
    管理员用户修改普通用户的状态
     */
    @Override
    public void updateUserStatus(UserStatusUpdateReqDTO updateDTO) {
        // 1. 判断用户是否为管理员用户
        LambdaQueryWrapper<User> adminWrapper = Wrappers.lambdaQuery(User.class)
                .eq(User::getUserId, updateDTO.getAdminUserId());
        User adminUser = baseMapper.selectOne(adminWrapper);

        if (adminUser == null) {
            throw new ClientException("管理员用户不存在");
        }

        if (adminUser.getUserType() != 2) {
            throw new ClientException(PERMISSION_DENIED);
        }

        // 2. 检查不能操作自己
        if (adminUser.getUsername().equals(updateDTO.getTargetUsername())) {
            throw new ClientException("不能修改自己的状态");
        }

        // 3. 检查目标用户是否存在且是普通用户
        LambdaQueryWrapper<User> targetWrapper = Wrappers.lambdaQuery(User.class)
                .eq(User::getUsername, updateDTO.getTargetUsername());
        User targetUser = baseMapper.selectOne(targetWrapper);

        if (targetUser == null) {
            throw new ClientException("目标用户不存在");
        }

        if (targetUser.getUserType() != 1) {
            throw new ClientException("只能修改普通用户的状态");
        }

        // 4. 更新普通用户状态
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class)
                .eq(User::getUsername, updateDTO.getTargetUsername())
                .set(User::getStatus, updateDTO.getStatus());

        int count = baseMapper.update(null, updateWrapper);
        if (count == 0) {
            throw new ClientException("用户状态更新失败");
        }

        // 5. 记录操作日志（可选）
        log.info("管理员[{}]将用户[{}]状态修改为: {}",
                updateDTO.getAdminUserId(),
                updateDTO.getTargetUsername(),
                updateDTO.getStatus());
    }


}
